#pragma once

#include <stdlib.h>
#include "RenderableUnit.h"
#include "../shared/shared_types.h"
#include "../engine/Singleton.h"
#include "../engine/Map.h"
#include "Ogre.h"
#include "OgreTextAreaOverlayElement.h"
#include "OgreFontManager.h"
#include <set>
#include <map>

#ifdef _DEBUG 
	#define CFG_FILE_PLUGINS "../configs/PutinPluginsD.cfg"
#else
	#define CFG_FILE_PLUGINS "../configs/PutinPlugins.cfg"
#endif

#define CFG_FILE_RESOURCES "../configs/PutinResources.cfg"
#define CFG_FILE_TERRAIN "../configs/maps/PutinTerrain.cfg"
#define HEIGHTMAP_FILE "../putinresources/maps/heightmap/putin.png"
#define USER_SETTINGS_STR "../configs/putin.cfg"
#define LOG_FILE "putin.log"

namespace Putin{

class RenderEngine : public Singleton< RenderEngine >
{
public:

	//Constructors
	RenderEngine( void );
	~RenderEngine( void );

	/**
	* Core Ogre scene manager object, left public for the WorldLink.
	*/
	Ogre::SceneManager* mSceneManager;

	void init();
	void loadMap( const std::string& fileName );
	void loadMap( Map* map );
	virtual void updateUnits( std::vector< RenderableUnit* > units );
	virtual void removeUnit( RenderableUnit* unit );
	void startRendering();
	void renderOneFrame();
	void setCameraLookAt( Vec3f position );
	void setCameraPosition( Vec3f position );
	void setSunDirection( Vec3f direction );
	void setCameraClipDistances( float nearClip, float farClip );
	void setRenderSystemConfigOption( std::string name, std::string value );
	int renderableUnitQuery( Vec2f mousePosition );
	Vec3f worldPositionQuery( Vec2f mousePosition );
	void showUnitBoundingBox( RenderableUnit* unit, bool showBounding );
	Ogre::AxisAlignedBox getUnitAABB( std::string unitId );
	Vec3f getUnitAABBhalfSize( std::string unitId );
	Vec3f getUnitOBBhalfSize( std::string unitId );
	void setTextOverlay( std::string text );
	void showTextOverlay( bool show );
	void setSkybox(std::string sb){mSkybox=sb;}
	HWND getWinHandle();
	Vec2i getWinSize();
	void addParticleEffect( std::string unitId, std::string effectName, bool toChild );
	void addParticleEffect( std::string name, std::string effectName, Vec3f worldLocation );
	void removeParticleEffect( std::string unitId, std::string effectName, bool fromChild );
	void removeParticleEffect( std::string name, std::string effectName, Vec3f worldLocation );
	
	friend class EngineController;  // to access the render window etc.

	//Used to generate map related stuff like i.e heightmaps
	static class MapTool 
	{
	public:
		static void generateHeightmapToImage( Map* map );
	};

private:
	/**
	* Core Ogre root object, left public for now. Prolly gonna be private.
	*/
	Ogre::Root* mRoot;

	/**
	* Core Ogre render window pointer.
	*/
	Ogre::RenderWindow* mWindow;
	
	/**
	* Core Ogre camera pointer.
	*/
	Ogre::Camera* mCamera;

	/**
	* Core Ogre viewport pointer.
	*/
	Ogre::Viewport* mViewport;

	/**
	* Core Ogre ray scene query pointer.
	*/
	Ogre::RaySceneQuery* mRaySceneQuery;
	
	/**
	* Sunlight pointer.
	*/
	Ogre::Light* mSunLight;

	/**
	 * Loaded Renderables. 
	 */ 
	std::set<std::string> mLoaded;
	
	/**
	 * Added effects. 
	 */ 
	std::map< std::string, std::set< std::string > > mParticleEffects;

	/**
	 * Stores the render system. 
	 */ 
	Ogre::RenderSystem* mRenderSystem;

	void createTextOverlay( void );

	std::string mSkybox;


};
}//End namespace Putin